package cn.tedu.ivos.base.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

//这是一个配置类，交由Spring管理
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CustomAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private CustomAuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private CustomAuthenticationProvider authenticationProvider;
    @Autowired
    private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置相关的认证和授权的信息
        http.csrf().disable()   //禁用csrf，关闭跨站请求保护
            .httpBasic()  //配置http基本认证信息
            .and().authorizeRequests() //配置请求授权，默认禁用所有请求
            .antMatchers(
                    "/doc.html",
                    "/**/*.js",
                    "/**/*.css",
                    "/swagger-resources",
                    "/v2/api-docs",
                    "/**"
            ).permitAll()  //对指定资源不进行权限检查,允许所有用户访问
            .anyRequest().authenticated() //对其他所有请求必须进行用户认证
            .and().formLogin()  //默认的请求地址为/login，配置表单登录
            .successHandler(authenticationSuccessHandler)  //认证成功后处理的操作
            .failureHandler(authenticationFailureHandler)  //认证失败后处理的操作
            .permitAll()
            .and().cors()  //配置跨域的信息
            .configurationSource(corsConfigurationSource())//将跨域配置源的信息提取到一个方法中完成
            .and().exceptionHandling() // 用户访问时没有权限，调用自定义的处理器
            .accessDeniedHandler(customAccessDeniedHandler)
            .authenticationEntryPoint(customAuthenticationEntryPoint)
        ; //允许所有用户进行登录尝试
    }

    /**
     * 配置CORS策略
     * @return CorsConfigurationSource 一个配置好跨域信息的对象
     */
    private CorsConfigurationSource corsConfigurationSource() {
        //1.创建一个CorsConfiguration对象
        CorsConfiguration cors = new CorsConfiguration();
        cors.setAllowCredentials(true); //允许请求携带凭证
        cors.addAllowedOriginPattern("*");//允许来自任何请求源的请求
        cors.addExposedHeader("*");//允许所有的请求头
        cors.addAllowedMethod("*"); //允许所有的请求方法
        cors.addExposedHeader("*");//允许响应头被客户端访问
        //创建一个CorsConfigurationSource，基于URL的CORS对象
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //将上面准备好的cors对象应用到URL中
        source.registerCorsConfiguration("/**",cors);
        return source;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.authenticationProvider(authenticationProvider);
    }
}
